"""
Manage commands even easier and allow decorated command functions.
"""
from utils.compat import cmdlib
from utils.debug import debug_wrap

@debug_wrap
def get_description(func):
    """
    Get a description from the function either from an attribute 'description'
    or from the docstring.
    
    @param func: function to get the description of.
    """
    if hasattr(func, 'description'):
        return func.description
    if func.__doc__:
        lines = filter(lambda x: x.strip(), func.__doc__.split('\n'))
        if lines:
            return lines[0]
    return "A Command"

@debug_wrap
def get_name(func):
    """
    Get the name of a command from a function either from an attribute or the
    actual function name.
    
    @param func: function to get the description of.
    """
    if hasattr(func, 'cmdname'):
        return func.cmdname
    return func.__name__

class CommandManager(object):
    """
    Manager of commands to unregister them.
    """
    def __init__(self):
        self.commands = {'server': [],
                         'client': [],
                         'say': []}
        
    @debug_wrap
    def _register(self, cmdtype, func):
        """
        Register a function for a certain command type.
        
        @param cmdtype: Type of the command.
        @param func: Function to register to the command.
        """
        description = get_description(func)
        cmdname = get_name(func)
        regfunc = getattr(cmdlib, 'register%sCommand' % (cmdtype.capitalize()))
        regfunc(cmdname, func, description)
        self.commands[cmdtype].append(cmdname)
        
    @debug_wrap
    def server_command(self, func):
        """
        Register a server command
        
        @param func: Function to register.
        """
        self._register('server', func)
        return func
    
    @debug_wrap
    def client_command(self, func):
        """
        Register a client command
        
        @param func: Function to register.
        """
        self._register('client', func)
        return func
    
    @debug_wrap
    def say_command(self, func):
        """
        Register a say command
        
        @param func: Function to register.
        """
        self._register('say', func)
        return func
    
    @debug_wrap
    def cleanup(self):
        """
        Unregister all commands registered to this manager.
        """
        for key, commands in self.commands.iteritems():
            unregfunc = getattr(cmdlib,
                                'unregister%sCommand' % (key.capitalize()))
            for cmd in commands:
                unregfunc(cmd)